package ch.sfug.display {
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.geom.Point;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.utils.Dictionary;
	import flash.utils.Timer;	

	/**
	 * @author loop
	 */
	public class ToolTip extends Sprite {

		private var t:DisplayObjectContainer;
		private var txts:Dictionary;
		private var delta:Point;
		private var timer:Timer;
		private var active:DisplayObject;

		public var label:TextField;
		public var bg:Sprite;

		
		public function ToolTip( target:DisplayObjectContainer = null ) {
			this.target = target;
			this.txts = new Dictionary();

			mouseEnabled = false;
			mouseChildren = false;

			delta = new Point(bg.width - label.width, bg.height - label.height);
			label.autoSize = TextFieldAutoSize.LEFT;
			timer = new Timer(0, 1);
			timer.addEventListener(TimerEvent.TIMER_COMPLETE, show);
		}

		
		/**
		 * registers a display object where a tooltip sould be shown
		 */
		public function register( dis:DisplayObject, text:String ):void {
			txts[ dis ] = text;
			dis.addEventListener(MouseEvent.MOUSE_OVER, onOver);
			dis.addEventListener(MouseEvent.MOUSE_OUT, onOut);
			
			// check if tooltip is visible
			if( target.contains(dis) ) this.text = txts[ dis ];
		}

		
		/**
		 * unregisters a display object from the tooltip
		 */
		public function unregister( dis:DisplayObject ):void {
			delete txts[ dis ];
			dis.removeEventListener(MouseEvent.MOUSE_OVER, onOver);
			dis.removeEventListener(MouseEvent.MOUSE_OUT, onOut);
		}

		
		/**
		 * catches the event when the mouse rolls over a registered display object
		 */
		private function onOver( me:MouseEvent ):void {
			var dis:DisplayObject = DisplayObject(me.currentTarget);
			if( dis == me.target ) {
				active = dis;
				timer.reset();
				timer.start();
			}
		}

		
		/**
		 * catches the event when the mouse rolls out of registered display object
		 * will hide the tooltip and remove to mouse move event
		 */
		private function onOut( me:MouseEvent ):void {
			if( timer.running ) {
				timer.stop();
			} else {
				hide();
			}
		}

		
		/**
		 * shows the tooltip
		 */
		private function show( e:Event = null ):void {
			onMove();
			if( !target.contains(this) ) target.addChild(this);
			text = txts[ active ];
			active.addEventListener(MouseEvent.MOUSE_MOVE, onMove);
		}

		
		private function hide():void {
			target.removeChild(this);
			active.removeEventListener(MouseEvent.MOUSE_MOVE, onMove);
			active = null;
		}

		
		/**
		 * catches the mouse move event. will adjust the position of the tooltip
		 */
		private function onMove( me:MouseEvent = null ):void {
			this.x = target.mouseX;
			this.y = target.mouseY;
		}

		
		/**
		 * sets the text of the tooltip
		 */
		public function set text( txt:String ):void {
			label.text = txt;
			bg.width = label.width + delta.x;
			bg.height = label.height + delta.y;
		}

		
		/**
		 * sets the target where the add the tooltip
		 */
		public function set target( tar:DisplayObjectContainer ):void {
			if( tar != null ) this.t = tar;
		}

		
		/**
		 * gets the target where the add the tooltip
		 */
		public function get target(  ):DisplayObjectContainer {
			return this.t;
		}

		
		/**
		 * sets the delay until to tooltip is shown
		 */
		public function set delay( msec:Number ):void {
			timer.delay = msec;
		}
	}
}
